問題解説: 弊社の変わった環境 (FreeBSD問題)

こんにちは。電気通信大学 学部1年の田中 京介こと kyontan です。

「cloudpack杯 第5回ICTトラブルシューティングコンテスト」では、FreeBSD を用いた問題を出題しました。
改めてその魅力を知っていただくと共に、出題した問題について、問題の概要や解説などをしていこうと思います。

概要

今回出題した問題は、FreeBSD と、その機能である Jail という仮想環境を用いた仮想ネットワークの構築を行うものでした。

出題意図として、皆さんが日頃から使っているであろう Linux とは異なった環境で新鮮な気持ちになって取り組んで頂けたらという気持ちがありました。また、最近 LXC, Docker を始めとしたコンテナ技術も流行っていますのでその先駆けとなった Jail の復権を……

出題時の構成は以下の通りでした。

  • ホストは FreeBSD 10.2-RELEASE
  • カーネルは 仮想ネットワーク機能 (VNET) を有効化したものをビルド、インストール済み
  • ホスト上で 5つの仮想化環境 (Jail) が動作し、それぞれ jail01, ..., jail05 といった Jail ID (jid) が割り当てられていた
  • ホストのみが  (参加者ネットワークへの) 対外接続 を持つ

また、出題時にはホストの root 権限を参加者に与えています。

問題の目標は、こちらが提示したトポロジ図に沿って Jail 間のネットワークを構築することでした。
トラブルシューティングというよりかは、情報収集・構築問題としての色が強い問題です。

問題文

ごく普通に卒業をし、ごく普通に就活をし、ごく普通の入社をしました。でも、ただひとつ違っていたのは、その会社では Linux ではないOSを使っていたのです。

「このOSは初めて? でも大丈夫! このOSには独自の仮想化環境があって、jls コマンドや epair, vnet を使って簡単に仮想ネットワークが構築できるよ。」
そんな事を言いながら、部長は、その仮想化環境が構築された環境 とトポロジ図を私に与えて続けるのです。

「仮想化ゲストを5台立てただけで何もしてないホストサーバを用意してあるよ。とりあえず jls を叩いてゲスト一覧を見たり、ゲスト上でコマンドを叩く方法を確認してみると良いよ。それができたら、練習がてらこれを構築してみてよ。今日中に構築すること! 終わったら、トポロジ図通りに繋がっていることの検証手順と結果を報告してね。

あと、可能ならばいくつかやってほしいことがあって……

構築手順をまとめてね
ゲストから外部 (google.com など) にもアクセスできるようにしてね
再起動してもそのトポロジが維持されるようにしてね (起動ごとに自動で構築しなおせば大丈夫だよ)
以上、よろしく!」

果たして私はこの会社でやっていけるのだろうか……

添付のトポロジ図は以下のとおりです。(Xは参加者のチーム番号です)

問題添付のトポロジ図

解説

まずはホストに入り 実際に Jail が動いているかどうかを確認しましょう。Jail の一覧の取得は、問題文にもある通り jls コマンドで行うことができます。
手元に問題の検証環境が既に無かったため、実際の自宅サーバーで jls を叩いた結果を貼ります。

[[email protected]]# jls
JID  IP Address      Hostname                   Path
1  -               cocoa.monora.me     /usr/jails/jails/cocoa
2  -               chino.monora.me     /usr/jails/jails/chino
3  -               megu.monora.me      /usr/jails/jails/megu
4  -               syaro.monora.me     /usr/jails/jails/syaro

上の例ですと、4つの Jail が動いていることや、それぞれの JID (Jail ID)、 どの Jail にも IPアドレスが振られていないことが分かります。
また、 Path はそれぞれの Jail の / としてマウントされるディレクトリのホストにおけるパスを示しています。

ここからは、ひたすら指示に沿ってトポロジ図の通りに IPアドレスを Jail に割り当てていく作業となります。

問題文でも触れられているとおり、FreeBSD には epair という仮想ネットワークI/F が存在し、仮想的なイーサネットケーブルとしての役割を果たします。

これは、 ifconfig epair create というコマンドを叩くことで作成可能で、作成すると epair0a, epair0b というように ab の2つのデバイスが一対となって作成されます。これをホストや Jail に割当てることで通信が可能になります。

具体的には、ifconfig epair0a vnet jail01 というコマンドを叩くことで、jail01 という Jail に epair0a側 (一方) を割り当てることができます。

この結果を確認するためには、 jail01 上で ifconfig を叩く必要があります。

Jail 上でのコマンド実行は jexec というコマンドを用います。使い方は jexec [jid] [command...] です。
jail01 上で ifconfig を叩く、という場合は、 jexec jail01 ifconfig というようになります。

ここまでが分かれば、トポロジ図にて与えられたネットワークアドレスからIPアドレスを適当に割り当てることで1:1 の通信が可能になります。

IPアドレスについては、トポロジ図で定められたネットワークアドレスを満たす範囲であれば好きに割り当てて大丈夫でした。

ちなみに、今大会の解答では、ここまでの手順で終了とする解答がとても多かったです。

FreeBSD のデフォルトでは、IPフォワーディングが無効になっているため、間に1台以上の端末を挟むと通信ができません。
実際に ping を叩けば分かりますが、この時点では jail02 - jail04, jail01 - jail05などの通信は行えません。
よって、IPフォワーディングを有効化にする必要があるホストをトポロジ図から判断し、jail01, jail02 に対して sysctlnet.inet.ip.forwarding を有効に (=1をセット) する必要がありました。

また、スタティックルート、デフォルトルートについても正しく設定する必要がありました。具体的なコマンドについては Appendix のスクリプトをお読みください。

以上の手順でトポロジ図通りにping, traceroute が通ることを確認したことを報告できていれば 満点の10点 でした。

加点課題

永続化

再起動しても同一の状況を構成できるようにするためには、FreeBSD の起動スクリプトである rc を用いる必要がありました。
具体的には、 /usr/local/etc/rc.d 以下に、前述の ifconfig 等の構築に用いたコマンド群を含んだ起動スクリプトを配置し、 /etc/rc.conf で再起動時に実行されるよう設定する必要がありました。

また、IPフォワーディングについても、永続化のために /etc/sysctl.conf に記述する必要がありました。

/usr/jail/jail01/etc/sysctl.conf, /usr/jail/jail02/etc/sysctl.conf

net.inet.ip.forwarding=1

起動スクリプトについては、長いため記事の最下部に記載してあります。

外部への疎通

外部への疎通については、 ブリッジを作成し、ホストの外部インタフェースと epair をブリッジにメンバとして加えた上で、 pf, ipfw などのファイアウォールを用いて NAT を構成することで構築が可能でした。

具体的には以下のような設定が必要でした。(pfを用いた場合)

/etc/rc.conf (追記分のみ)

pf_enable="YES"

gateway_enable="YES"
cloned_interfaces="bridge0"
ifconfig_bridge="addm em0"
ifconfig_epair0a="inet 10.X.11.3/29"

static_routes="jailnet"
route_jailnet="-net 10.X.11.0/27 10.x.11.4"

/etc/pf.conf

# vtnet0 は 場合に応じて書き換える
ext_if="vtnet0"

table <private> const {10.X.11.0/27}

nat on $ext_if inet from 10.X.11.0/27 to !<private> -> ($ext_if)

/etc/sysctl.conf

net.inet.ip.forwarding=1

採点基準

採点は、提出された解答内で示された報告の内容を見た上で、実際にホストに ssh で入り、ping, traceroute を叩いて疎通が取れるかを確認して行いました。全 Jail の組み合わせ計10通りに対し、トポロジ図の通りに通信ができていることで各1点の配点としました。
また、報告内容が充実しているものや、加点課題について解決法を提案しているもの等については5点を最大として加点を行いました。

講評・感想

問題文ではあえて “FreeBSD” という名前を直接出さず、 Jail という表現にとどめましたが、FreeBSD であることはすぐに分かったというチームが多かったようです。
個人的には挑戦することに躊躇されるチームが多いのかと想像していましたが、大会での解答率は想像を上回り、4割を超えるチームに解答を頂きました。ありがとうございました。

日頃使い慣れていない環境なのは重々承知ですが、”FreeBSD Jail”, “Jail epair” 等で検索すると、それなりに日本語でも構築手順をまとめたサイトが多く出てくるため、それらを参照すると比較的簡単に10点までは辿り着けたのではないかと思っています。ただ、IPアドレスを手計算したり、なかなか単純作業で心を折ってくる問題構成になってしまったのは反省しているところです。

Appendix

/usr/local/etc/rc.d/ictsc_conf

#!/bin/sh
#
# PROVIDE: ictsc_conf
# REQUIRE: jail

. /etc/rc.subr

name="ictsc_conf"
rcvar=`set_rcvar`

load_rc_config ${name}

start_cmd="${name}_start"

: ${ictsc_conf_enable="NO"}

ictsc_conf_start() {
echo -n "Starting ${name}"

ifconfig bridge0 create
ifconfig epair0 create
ifconfig epair1 create
ifconfig epair2 create
ifconfig epair3 create
ifconfig epair4 create

ifconfig bridge0 addm em0
ifconfig bridge0 addm epair0a

ifconfig epair0b vnet jail01
ifconfig epair1a vnet jail01
ifconfig epair2a vnet jail01
ifconfig epair3a vnet jail01

ifconfig epair1b vnet jail02
ifconfig epair4a vnet jail02

ifconfig epair2b vnet jail03

ifconfig epair3b vnet jail04

ifconfig epair4b vnet jail05

ifconfig epair0a 10.X.11.3/29 up

jexec jail01 ifconfig epair0b 10.X.11.4/29 up
jexec jail01 ifconfig epair1a 10.X.11.9/30 up
jexec jail01 ifconfig epair2a 10.X.11.13/30 up
jexec jail01 ifconfig epair3a 10.X.11.17/30 up

jexec jail02 ifconfig epair1b 10.X.11.10/30 up
jexec jail02 ifconfig epair4a 10.X.11.21/30 up

jexec jail03 ifconfig epair2b 10.X.11.14/30 up

jexec jail04 ifconfig epair3b 10.X.11.18/30 up

jexec jail05 ifconfig epair4b 10.X.11.22/30 up

# route add -net 10.X.11.0/27 10.X.11.4

jexec jail01 route add -net default 10.X.11.3
jexec jail02 route add -net default 10.X.11.9
jexec jail03 route add -net default 10.X.11.13
jexec jail04 route add -net default 10.X.11.17
jexec jail05 route add -net default 10.X.11.21

jexec jail01 route add -net 10.X.11.20/30 10.X.11.10
}

run_rc_command $1

/etc/rc.conf (追記分)

ictsc_conf_enable="YES"

最後に

長々とした説明になってしまいましたが、FreeBSD はいかがでしたでしょうか?
軽量な OS 本体と Jail の組み合わせは中々の使い心地を提供してくれること請け合いです。

興味を持たれた方はこの機会にインストールされてみるのも良いのではないでしょうか。

最後までお付き合い頂き、ありがとうございました。